package com.smec;
import java.awt.event.ComponentListener;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.UnaryOperator;

/**
 * @ClassName FFT
 * @Description 用于计算输入数据的FFT变换
 * @Author u3431
 * @Date 2021/12/28 10:41
 * @Version 1.0
 */

public class FFT {
    private static final double PI = 3.14159265358979323846;
    static public UnaryOperator<List<FftDTO>> fftsolver = FFT::fft;


    static private List<FftDTO> fft(List<FftDTO> inputData){
        int n = inputData.size();
        try {
            if( (n == (int)Math.pow(2,9))||
                (n == (int)Math.pow(2,10))||
                (n == (int)Math.pow(2,11))||
                (n == (int)Math.pow(2,12))||
                (n == (int)Math.pow(2,13))) {
                List<FftDTO> output = new ArrayList<>();
                FftDTO fftDto = new FftDTO();
                int s = 0;
                s = (int)(Math.log(n)/Math.log(2));
                int[] rev = Utils.bitReverseCopy(n);
                List<Complex> A = Utils.bitReverseCopy(rev, inputData);
                int m = 0;//当前计算层的系数个数
                Complex w_m = new Complex(0f, 0f);//当前计算层对应的基函数
                Complex w = new Complex(0f, 0f);
                Complex t = new Complex(0f, 0f);
                Complex u = new Complex(0f, 0f);
                //最外层循环对应求解问题的规模，从规模2开始才有计算意义，规模1就是系数或输入信号
                for (int i = 1; i <= s; i++) {
                    m = (int) Math.pow(2, i);
                    w_m.setReal((float) Math.cos(2 * PI / m));
                    w_m.setImage((float) Math.sin(2 * PI / m));
                    //k循环对应的是当前层分了几个子问题，即需要计算多少个，因此步长是当前子问题的规模
                    for (int k = 0; k <= n - 1; k+=m) {
                        w.setReal(1);
                        w.setImage(0);
                        //j循环对应的是需要用到多少次的基函数w_n
                        for (int j = 0; j <= m / 2 - 1; j++) {
                            t = Complex.multiply(w, A.get(k+j+m/2));
                            u.setReal(A.get(k+j).getReal());
                            u.setImage(A.get(k+j).getImage());
                            A.get(k + j).setReal(u.getReal() + t.getReal());
                            A.get(k + j).setImage(u.getImage() + t.getImage());
                            A.get(k + j + m/2).setReal(u.getReal() - t.getReal());
                            A.get(k + j + m/2).setImage(u.getImage() - t.getImage());
                            w.multiply(w_m);
                        }
                    }
                }
                Float buffer;//用来
                FftDTO temp;
                long index = 1;
                for (Complex complex:A
                     ) {
                    temp = new FftDTO();
                    temp.setTime("0");
                    temp.setId(index);
                    //将输出的单位改为gals
                    buffer = Float.parseFloat(complex.abs())/n * 100;
                    temp.setValue(String.valueOf(buffer));
                    output.add(temp);
                    index += 1;
                }
                return output;
            }else{
                throw new InputLengthException();
            }
        } catch (InputLengthException e) {
            e.printStackTrace();
        }
        return null;
    }

}

